package com.zf.zffencheng.interceptor;

import com.zf.zffencheng.exception.Error_;
import com.zf.zffencheng.exception.ResultException;
import com.zf.zffencheng.model.vo.AdminLoginInfoVo;
import com.zf.zffencheng.service.AdminService;
import com.zf.zffencheng.util.UserContextUtils;
import lombok.extern.log4j.Log4j2;
import org.redisson.api.RBucket;
import org.redisson.api.RedissonClient;
import org.redisson.codec.JsonJacksonCodec;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.concurrent.TimeUnit;

/**
 * ClassName: interceptor <br/>
 * Description:  <br/>
 * date: 2021/5/10 9:32<br/>
 *
 * @author william <br/>
 */
@Component
@Log4j2
public class SapiInterceptor extends HandlerInterceptorAdapter {
    @Autowired
    private RedissonClient redissonClient;

    public static final String AUTHORIZATION_HEADER ="Authorization";
    public static final String BEARER ="Bearer ";
    public static final int BEARER_LENGTH = BEARER.length();
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        UserContextUtils.clean();
        String method = request.getMethod();
        String requestUri = request.getRequestURI();
        String remoteAddr = request.getRemoteAddr();
        String header = request.getHeader(AUTHORIZATION_HEADER);
        log.info("【请求方式：{} \t, 请求地址:{} \t, 请求ip:{} ,请求access_token:{}\t】", method, requestUri, remoteAddr, header);

        //白名单
        long contains = Arrays.stream(WHITE_LIST).filter(val->requestUri.indexOf(val)>0).count();
        log.info("是否有白名单存在:{}", contains);
        if(contains>0){
            //白名单通过
            return true;
        }else{
            String headerToken = getHeaderToken(header);
            //从令牌桶拿数据
            RBucket<AdminLoginInfoVo> bucket = redissonClient.getBucket(AdminService.LOGIN_TOKEN_BUCKET.concat(":").concat(headerToken)
                    ,new JsonJacksonCodec());
            if(!bucket.isExists()){
                throw new ResultException(Error_.AUTHORIZATION_FAIL);
            }
            //异步延长时间
            bucket.expireAsync(AdminService.LOGIN_EXPIRE, TimeUnit.SECONDS);

            AdminLoginInfoVo adminLoginInfoVo = bucket.get();
            UserContextUtils.setUsers(adminLoginInfoVo);
        }
        return true;
    }

    public String getHeaderToken(String header){
        //授权
        if(StringUtils.hasLength(header) && header.length() > BEARER_LENGTH){
            return header.substring(BEARER_LENGTH);
        }else{
            //授权失败
            throw new ResultException(Error_.AUTHORIZATION_FAIL);
        }
    }

    private static final String[] WHITE_LIST = {
            //登录
            "/sapi/v1/login/admin",
            //短消息
            "/sapi/v1/sms/send",
    };


}
